package com.zbkj.crmeb.store.service.impl;

import com.alibaba.druid.sql.visitor.functions.Isnull;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.constants.Constants;
import com.crmeb.core.exception.CrmebException;
import com.utils.CrmebUtil;
import com.utils.DateUtil;
import com.utils.vo.dateLimitUtilVo;
import com.zbkj.crmeb.store.dao.StoreOrderDao;
import com.zbkj.crmeb.store.model.StoreOrder;
import com.zbkj.crmeb.store.model.StoreOrderInfo;
import com.zbkj.crmeb.store.response.DataLiveResponse;
import com.zbkj.crmeb.store.response.DataLiveSingleResponse;
import com.zbkj.crmeb.store.response.TransactionUserResponse;
import com.zbkj.crmeb.store.service.CustomerProfileService;
import com.zbkj.crmeb.store.service.DataLiveService;
import com.zbkj.crmeb.store.service.StoreOrderInfoService;
import com.zbkj.crmeb.store.service.StoreOrderService;
import com.zbkj.crmeb.user.dao.UserMemberRecordDao;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.model.UserMemberRecord;
import com.zbkj.crmeb.user.service.UserMemberRecordService;
import com.zbkj.crmeb.user.service.UserService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.tomcat.jni.Local;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.chrono.ChronoLocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CustomerProfileServiceImpl implements CustomerProfileService {

    @Autowired
    private UserService userService;
    @Autowired
    private UserMemberRecordService userMemberRecordService;
    @Resource
    private UserMemberRecordDao userMemberRecordDao;
    @Autowired
    private DataLiveService dataLiveService;
    @Resource
    private StoreOrderDao storeOrderDao;
    @Autowired
    private StoreOrderInfoService storeOrderInfoService;

    /**
     * 功能描述: 客户概况
     * @Param: [dateLimit, merId]
     * @Return: java.util.Map<java.lang.String,java.lang.Object>
     * @Author: wangzh
     * @Date: 2023/1/6 9:33
     */
    @Override
    public Map<String, Object> customerProfileBoard(dateLimitUtilVo dateLimit, Integer merId) {
        Map<String, Object> response = new HashMap<>();
        LocalDate startTime = LocalDate.parse(dateLimit.getStartTime());
        LocalDate endTime = LocalDate.parse(dateLimit.getEndTime());
        //相隔时间
        int interval = (int) (startTime.until(endTime, ChronoUnit.MONTHS) + 1);
        if (interval > 3){
            throw new CrmebException("月份超出限制，最大选取三个月");
        }
        //上次时间段
        LocalDate previousStartTime = startTime.minusMonths(interval);
        LocalDate previousEndTime = endTime.minusMonths(interval);
        //开始结束时间相差天数
        int len = (int) (startTime.until(endTime, ChronoUnit.DAYS) + 1);
        //每个节点中间相差的天数
        int intervalDay;
        if (len % 15 < 7){
            intervalDay = len / 15;
        } else {
            intervalDay = len / 15 + 1;
        }
        //时间列表
        List<String> listDateMonth = DateUtil.getListDateMonth(dateLimit, 15);
        dateLimitUtilVo previousDateLimit = new dateLimitUtilVo(previousStartTime.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), previousEndTime.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END)));
        //新增用户数
        response.put("userAdd", getAddUserCount(listDateMonth, previousDateLimit, merId, intervalDay));
        //新增付费会员数
        response.put("paidMember", getPaidMember(listDateMonth, previousDateLimit, merId, intervalDay));
        //累计用户数量
        DataLiveSingleResponse cumulativeUser = getCumulativeUser(listDateMonth, previousDateLimit, merId, intervalDay);
        response.put("cumulativeUser", cumulativeUser);
        //累计付费会员占比
        response.put("cumulativePaidUser", getCumulativePaidUser(listDateMonth, previousDateLimit, merId, intervalDay, cumulativeUser));

        return response;
    }

    /**
     * 功能描述: 用户成交
     * @Param: [dateLimit, merId]
     * @Return: com.zbkj.crmeb.store.response.DataLiveResponse
     * @Author: wangzh
     * @Date: 2023/1/6 10:24
     */
    @Override
    public DataLiveResponse customerTransaction(dateLimitUtilVo dateLimit, Integer merId) {
        DataLiveResponse response = new DataLiveResponse();
        LocalDate startTime = LocalDate.parse(dateLimit.getStartTime());
        LocalDate endTime = LocalDate.parse(dateLimit.getEndTime());
        //相隔时间
        int interval = (int) (startTime.until(endTime, ChronoUnit.MONTHS) + 1);
        if (interval > 3){
            throw new CrmebException("月份超出限制，最大选取三个月");
        }
        //上次时间段
        LocalDate previousStartTime = startTime.minusMonths(interval);
        LocalDate previousEndTime = endTime.minusMonths(interval);
        //开始结束时间相差天数
        int len = (int) (startTime.until(endTime, ChronoUnit.DAYS) + 1);
        //每个节点中间相差的天数
        int intervalDay;
        if (len % 15 < 7){
            intervalDay = len / 15;
        } else {
            intervalDay = len / 15 + 1;
        }
        //时间列表
        List<String> listDateMonth = DateUtil.getListDateMonth(dateLimit, 15);
        dateLimitUtilVo previousDateLimit = new dateLimitUtilVo(previousStartTime.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), previousEndTime.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END)));

        //支付用户数
        DataLiveSingleResponse payNum = dataLiveService.getWholePayNum(listDateMonth, Arrays.asList(merId), previousDateLimit, intervalDay);
        response.setPayNum(payNum);
        //用户支付金额
        DataLiveSingleResponse payMoney = dataLiveService.getWholePayMoney(listDateMonth, Arrays.asList(merId), previousDateLimit, intervalDay);
        response.setPayMoney(payMoney);
        //用户客单价
        DataLiveSingleResponse customerUnitPrice = dataLiveService.getWholeCustomerUnitPrice(payMoney, dataLiveService.getWholePayOrder(listDateMonth, Arrays.asList(merId), previousDateLimit, intervalDay));
        response.setCustomerUnitPrice(customerUnitPrice);
        return response;
    }

    /**
     * 功能描述: 成交用户概况（类型）
     * @Param: [dateLimit, merId]
     * @Return: java.util.Map<java.lang.String,java.lang.Object>
     * @Author: wangzh
     * @Date: 2023/1/6 15:24
     */
    @Override
    public Map<String, Object> customerTransactionByType(dateLimitUtilVo dateLimit, Integer merId) {
        Map<String, Object> response = new HashMap<>();
        LocalDate startTime = LocalDate.parse(dateLimit.getStartTime());
        LocalDate endTime = LocalDate.parse(dateLimit.getEndTime());
        //相隔时间
        int interval = (int) (startTime.until(endTime, ChronoUnit.MONTHS) + 1);
        if (interval > 3){
            throw new CrmebException("月份超出限制，最大选取三个月");
        }
        String startTimeStr = startTime.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
        String endTimeStr = endTime.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
        //新用户判断时间
        String newUserStartTime = endTime.minusDays(90).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_DATE));
        dateLimitUtilVo dateLimitUtilVo = new dateLimitUtilVo(startTimeStr, endTimeStr);
        //全部用户成交情况
        TransactionUserResponse all = getTransactionUserByType(dateLimitUtilVo, merId, null);
        all.setUserNumberRate("100%").setPayPriceRate("100%");
        //全部用户
        response.put("allUser", all);
        List<Integer> newUserUid = new ArrayList<>();
        List<User> list = userService.list(Wrappers.<User>lambdaQuery()
                .eq(User::getMerId, merId)
                .between(User::getCreateTime, newUserStartTime, endTimeStr));
        //给新用户id赋值
        if (CollectionUtils.isNotEmpty(list)){
            newUserUid = list.stream().map(User::getUid).collect(Collectors.toList());
        } else {
            //确保list不为空
            newUserUid.add(0);
        }
        //新用户
        TransactionUserResponse newUser = getTransactionUserByType(dateLimitUtilVo, merId, newUserUid);
        TransactionUserResponse oldUser = new TransactionUserResponse();
        //新用户成交概况为0，老用户等于全部用户
        if (newUser.getTransactionUserNumber() == 0){
            oldUser = all;
            newUser.setUserNumberRate("0%");
            newUser.setPayPriceRate("0%");
        } else {
            //新用户客户数占比
            BigDecimal newUserNumberRate = new BigDecimal(newUser.getTransactionUserNumber()).divide(new BigDecimal(all.getTransactionUserNumber()), 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
            //新用户支付金额占比
            BigDecimal newUserPayPriceRate = newUser.getPayPrice().divide(all.getPayPrice(), 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
            newUser.setUserNumberRate(newUserNumberRate + "%").setPayPriceRate(newUserPayPriceRate + "%");
            oldUser.setTransactionUserNumber(all.getTransactionUserNumber() - newUser.getTransactionUserNumber());
            oldUser.setUserNumberRate(new BigDecimal(100).subtract(newUserNumberRate) + "%");
            oldUser.setOrderNumber(all.getOrderNumber() - newUser.getOrderNumber());
            oldUser.setPayPrice(all.getPayPrice().subtract(newUser.getPayPrice()));
            BigDecimal customerUnitPrice = oldUser.getPayPrice();
            if (oldUser.getOrderNumber() > 0){
                customerUnitPrice = customerUnitPrice.divide(new BigDecimal(oldUser.getOrderNumber()), 2, RoundingMode.HALF_UP);
            }
            oldUser.setCustomerUnitPrice(customerUnitPrice);
            oldUser.setPayPriceRate(new BigDecimal(100).subtract(newUserPayPriceRate) + "%");
        }
        //新用户
        response.put("newUser", newUser);
        //老用户
        response.put("oldUser", oldUser);
        return response;
    }

    @Override
    public Map<String, Map<String, Object>> customerTransactionByDate(Integer merId) {
        Map<String, Map<String, Object>> response = getMonth();
        //获取每个时间段新成交用户数
        for (String key : response.keySet()){
            List<Integer> uids = new ArrayList<>();
            //当月新增用户
            List<User> list = userService.list(Wrappers.<User>lambdaQuery()
                    .eq(User::getMerId, merId)
                    .likeRight(User::getCreateTime, key));
            //新增用户为空，其余全为0
            if (CollectionUtils.isEmpty(list)){
                uids.add(0);
            } else {
                uids = list.stream().map(User::getUid).collect(Collectors.toList());
            }
            //查询新授权并有订单记录的用户数量
            Integer userNumber = storeOrderDao.getPayOrderUserNum(Wrappers.<StoreOrder>lambdaQuery()
                    .in(StoreOrder::getUid, uids)
                    .eq(StoreOrder::getMerId, merId)
                    .likeRight(StoreOrder::getCreateTime, key)
                    .eq(StoreOrder::getPaid, 1)
                    .groupBy(StoreOrder::getUid));

            DateTimeFormatter fmt = new DateTimeFormatterBuilder()
                    .appendPattern("yyyy-MM")
                    .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
                    .toFormatter();
            LocalDate localDate = LocalDate.parse(key, fmt);
            //当前月的留存情况
            Map<String, Object> map = new HashMap<>();
            int mapKey = 1;
            while (localDate.isBefore(LocalDate.now()) && !localDate.isEqual(LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()))){
                int count = 0;
                localDate = localDate.plusMonths(1);
                //最大计算4个月
                if (mapKey > 4){
                    break;
                }
                //判断留存情况
                for (User user : list){
                    //用户最后一次登陆时间在月份之后，说明留存
                    if (user.getLastLoginTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().isAfter(localDate)){
                        count ++;
                    }
                }
                map.put(String.valueOf(mapKey), count);
                mapKey ++;
            }
            map.put("newTransactionUserNumber", userNumber);
            response.put(key, map);
        }
        return response;
    }

    /**
     * 功能描述: 获取新增用户数
     * @Param: [dateList, dateLimit, merId, intervalDay]
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2023/1/4 17:12
     */
    private DataLiveSingleResponse getAddUserCount(List<String> dateList, dateLimitUtilVo dateLimit, Integer merId, Integer intervalDay){
        String startTimeStr = LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
        String endTimeStr = LocalDate.parse(dateList.get(dateList.size() - 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
        String date = startTimeStr + "," + endTimeStr;
        //选择时间内新增用户数量
        Integer present = userService.getAddUserCountByDate(date, Arrays.asList(merId));
        //上次时间段内新增用户数量
        Integer previous = userService.getAddUserCountByDate(dateLimit.getStartTime() + "," + dateLimit.getEndTime(), Arrays.asList(merId));
        BigDecimal rate = CrmebUtil.getRateDecimal(present, previous);
        Map<Object, Object> userAddMap = new LinkedHashMap<>();
        userAddMap.put(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_DATE)) + "~" + dateList.get(0), userService.getAddUserCountByDate(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)) + "," + LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END)), Arrays.asList(merId)));
        for (int i = 0; i < dateList.size() - 1; i++) {
            String start = LocalDate.parse(dateList.get(i)).plusDays(1).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
            String end = LocalDate.parse(dateList.get(i + 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
            userAddMap.put(LocalDate.parse(dateList.get(i)).plusDays(1) + "~" + dateList.get(i + 1), userService.getAddUserCountByDate(start + "," + end, Arrays.asList(merId)));
        }
        userAddMap = CrmebUtil.convertKey(userAddMap);
        DataLiveSingleResponse userAdd = new DataLiveSingleResponse();
        userAdd.setTodayCount(present)
                .setYesterdayCount(previous)
                .setMonthRate(rate + "%")
                .setLineChart(userAddMap);
        return userAdd;
    }

    /**
     * 功能描述: 新增付费会员数
     * @Param: [dateList, dateLimit, merId, intervalDay]
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2023/1/5 14:44
     */
    private DataLiveSingleResponse getPaidMember(List<String> dateList, dateLimitUtilVo dateLimit, Integer merId, Integer intervalDay){
        String startTimeStr = LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
        String endTimeStr = LocalDate.parse(dateList.get(dateList.size() - 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
        //选择时间段新增数量
        Integer present = getPaidMemberCount(new dateLimitUtilVo(startTimeStr, endTimeStr), merId);
        //上一个时间段新增数量
        Integer previous = getPaidMemberCount(dateLimit, merId);
        BigDecimal rate = CrmebUtil.getRateDecimal(present, previous);
        Map<Object, Object> paidMemberMap = new LinkedHashMap<>();
        paidMemberMap.put(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_DATE)) + "~" + dateList.get(0), getPaidMemberCount(new dateLimitUtilVo(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END))), merId));
        for (int i = 0; i < dateList.size() - 1; i++) {
            String start = LocalDate.parse(dateList.get(i)).plusDays(1).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
            String end = LocalDate.parse(dateList.get(i + 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
            paidMemberMap.put(LocalDate.parse(dateList.get(i)).plusDays(1) + "~" + dateList.get(i + 1), getPaidMemberCount(new dateLimitUtilVo(start, end), merId));
        }
        paidMemberMap = CrmebUtil.convertKey(paidMemberMap);
        DataLiveSingleResponse paidMember = new DataLiveSingleResponse();
        paidMember.setTodayCount(present)
                .setYesterdayCount(previous)
                .setMonthRate(rate + "%")
                .setLineChart(paidMemberMap);
        return paidMember;
    }

    /**
     * 功能描述: 累计用户数量
     * @Param: [dateList, dateLimit, merId, intervalDay]
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2023/1/5 17:15
     */
    private DataLiveSingleResponse getCumulativeUser(List<String> dateList, dateLimitUtilVo dateLimit, Integer merId, Integer intervalDay){
        String endTimeStr = LocalDate.parse(dateList.get(dateList.size() - 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
        //选择时间段内累计用户数量
        Integer present = getCumulativeUserCount(endTimeStr, merId);
        //上一期数量
        Integer previous = getCumulativeUserCount(dateLimit.getEndTime(), merId);
        BigDecimal rate = CrmebUtil.getRateDecimal(present, previous);
        Map<Object, Object> cumulativeUserMap = new LinkedHashMap<>();
        cumulativeUserMap.put(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_DATE)) + "~" + dateList.get(0), getCumulativeUserCount(LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END)), merId));
        for (int i = 0; i < dateList.size() - 1; i++) {
            String end = LocalDate.parse(dateList.get(i + 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
            cumulativeUserMap.put(LocalDate.parse(dateList.get(i)).plusDays(1) + "~" + dateList.get(i + 1), getCumulativeUserCount(end, merId));
        }
        cumulativeUserMap = CrmebUtil.convertKey(cumulativeUserMap);
        DataLiveSingleResponse cumulativeUser = new DataLiveSingleResponse();
        cumulativeUser.setTodayCount(present)
                .setYesterdayCount(previous)
                .setMonthRate(rate + "%")
                .setLineChart(cumulativeUserMap);
        return cumulativeUser;
    }

    /**
     * 功能描述: 获取付费会员占比
     * @Param: [dateList, dateLimit, merId, intervalDay, cumulativeUser]
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2023/1/5 17:44
     */
    private DataLiveSingleResponse getCumulativePaidUser(List<String> dateList, dateLimitUtilVo dateLimit, Integer merId, Integer intervalDay, DataLiveSingleResponse cumulativeUser){
        String endTimeStr = LocalDate.parse(dateList.get(dateList.size() - 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
        //选择时间段内累计付费会员数量
        Integer presentPaid = getCumulativePaidUserCount(endTimeStr, merId);
        //上一期累计付费会员数
        Integer previousPaid = getCumulativePaidUserCount(dateLimit.getEndTime(), merId);

        //选择时间段内累计用户数量
        Integer presentUser = (Integer) cumulativeUser.getTodayCount();
        //上一期
        Integer previousUser = (Integer) cumulativeUser.getYesterdayCount();

        //选择时间占比
        BigDecimal present = new BigDecimal(presentPaid);
        if (presentUser > 0){
            present = new BigDecimal(presentPaid).divide(new BigDecimal(presentUser), 2, RoundingMode.HALF_UP);
        }
        //上期占比
        BigDecimal previous = new BigDecimal(previousPaid);
        if (previousUser > 0){
            previous = new BigDecimal(previousPaid).divide(new BigDecimal(previousUser), 2, RoundingMode.HALF_UP);
        }
        BigDecimal rate = CrmebUtil.getRateDecimal(present, previous);
        Map<Object, Object> cumulativePaidUserMap = new LinkedHashMap<>();
        cumulativePaidUserMap.put(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_DATE)) + "~" + dateList.get(0), getCumulativePaidUserCount(LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END)), merId));
        for (int i = 0; i < dateList.size() - 1; i++) {
            String end = LocalDate.parse(dateList.get(i + 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
            cumulativePaidUserMap.put(LocalDate.parse(dateList.get(i)).plusDays(1) + "~" + dateList.get(i + 1), getCumulativePaidUserCount(end, merId));
        }
        cumulativePaidUserMap = CrmebUtil.convertKey(cumulativePaidUserMap);
        DataLiveSingleResponse cumulativePaidUser = new DataLiveSingleResponse();
        cumulativePaidUser.setTodayCount(present)
                .setYesterdayCount(previous)
                .setMonthRate(rate + "%")
                .setLineChart(cumulativePaidUserMap);
        return cumulativePaidUser;
    }

    /**
     * 功能描述: 获取全部用户/新用户成交概况
     * @Param: [dateLimit, merId, newUser]
     * @Return: com.zbkj.crmeb.store.response.TransactionUserResponse
     * @Author: wangzh
     * @Date: 2023/1/6 14:18
     */
    private TransactionUserResponse getTransactionUserByType(dateLimitUtilVo dateLimit, Integer merId, List<Integer> newUser){
        //是否查询新用户
        boolean isNew = CollectionUtils.isNotEmpty(newUser);
        String inSql = "select id from eb_store_order where mer_id = " + merId + " and create_time between '" + dateLimit.getStartTime() + "' and '" + dateLimit.getEndTime() +"'";
        if (isNew){
            String uidList = "(" + newUser.stream().map(String::valueOf).collect(Collectors.joining(",")) + ")";
            inSql = inSql + " and uid in " + uidList;
        }
        LambdaQueryWrapper<StoreOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.ne(StoreOrder::getStatus, 0)
                .ne(StoreOrder::getStatus, 5)
                .eq(StoreOrder::getMerId, merId)
                //新用户
                .in(isNew, StoreOrder::getUid, newUser)
                .between(StoreOrder::getCreateTime, dateLimit.getStartTime(), dateLimit.getEndTime())
                .groupBy(StoreOrder::getUid);
        //时间段内全部支付用户数
        Integer payOrderUserNum = storeOrderDao.getPayOrderUserNum(lambdaQueryWrapper);

        QueryWrapper<StoreOrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("count(*) as id", "sum(pay_price + deduction_price) as pay_price")
                        .lambda().ne(StoreOrderInfo::getStatus, 0)
                        .ne(StoreOrderInfo::getStatus, 5)
                        .inSql(StoreOrderInfo::getOrderId, inSql)
                        .between(StoreOrderInfo::getCreateTime, dateLimit.getStartTime(), dateLimit.getEndTime());
        StoreOrderInfo one = storeOrderInfoService.getOne(queryWrapper);
        //支付订单数
        Integer orderNumber = one.getId();
        //支付金额
        BigDecimal payPrice = one.getPayPrice() == null ? BigDecimal.ZERO : one.getPayPrice();
        //客单价
        BigDecimal customerUnitPrice = payPrice;
        if (orderNumber > 0){
            customerUnitPrice = payPrice.divide(new BigDecimal(orderNumber), 2, RoundingMode.HALF_UP);
        }
        TransactionUserResponse response = new TransactionUserResponse();
        response.setTransactionUserNumber(payOrderUserNum)
                .setOrderNumber(orderNumber)
                .setPayPrice(payPrice)
                .setCustomerUnitPrice(customerUnitPrice);
        return response;
    }

    /**
     * 功能描述: 获取指定时间内新增付费会员数
     * @Param: [dateLimit, merId]
     * @Return: java.lang.Integer
     * @Author: wangzh
     * @Date: 2023/1/5 10:48
     */
    private Integer getPaidMemberCount(dateLimitUtilVo dateLimit, Integer merId){
        List<UserMemberRecord> list = userMemberRecordService.list(Wrappers.<UserMemberRecord>lambdaQuery()
                .eq(UserMemberRecord::getMerId, merId)
                .eq(UserMemberRecord::getPaid, 1)
                .lt(UserMemberRecord::getCreateTime, dateLimit.getStartTime())
                .groupBy(UserMemberRecord::getUid));
        //已经开通过付费会员的用户id
        List<Integer> hasUid = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)){
            hasUid = list.stream().map(UserMemberRecord::getUid).collect(Collectors.toList());
        }
        return userMemberRecordDao.getPaidMemberCount(Wrappers.<UserMemberRecord>lambdaQuery()
                .eq(UserMemberRecord::getMerId, merId)
                .eq(UserMemberRecord::getPaid, 1)
                .between(UserMemberRecord::getCreateTime, dateLimit.getStartTime(), dateLimit.getEndTime())
                .notIn(CollectionUtils.isNotEmpty(hasUid), UserMemberRecord::getUid, hasUid)
                .groupBy(UserMemberRecord::getUid));
    }

    /**
     * 功能描述: 获取累计用户数量
     * @Param: [date, merId]
     * @Return: java.lang.Integer
     * @Author: wangzh
     * @Date: 2023/1/5 17:03
     */
    private Integer getCumulativeUserCount(String date, Integer merId){
        return userService.count(Wrappers.<User>lambdaQuery()
                .eq(User::getMerId, merId)
                .le(User::getCreateTime, date));
    }

    /**
     * 功能描述: 获取累计付费会员数量
     * @Param: [date, merId]
     * @Return: java.lang.Integer
     * @Author: wangzh
     * @Date: 2023/1/5 17:19
     */
    private Integer getCumulativePaidUserCount(String date, Integer merId){
        return userMemberRecordDao.getPaidMemberCount(Wrappers.<UserMemberRecord>lambdaQuery()
                .eq(UserMemberRecord::getMerId, merId)
                .gt(UserMemberRecord::getExpirationTime, date)
                .groupBy(UserMemberRecord::getUid));
    }

    /**
     * 功能描述: 获取成交用户概况时间坐标
     * @Param: []
     * @Return: java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.Object>>
     * @Author: wangzh
     * @Date: 2023/1/6 15:31
     */
    private Map<String, Map<String, Object>> getMonth(){
        Map<String, Map<String, Object>> map = new LinkedHashMap<>();
        LocalDate now = LocalDate.now();
        LocalDate start = now.minusMonths(5);
        while (start.isBefore(now)){
            map.put(start.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_MONTH)), null);
            start = start.plusMonths(1);
        }
        map.put(now.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_MONTH)), null);
        return map;
    }
}
